package com.lwd.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.fastjson.serializer.JSONSerializer;
import com.alibaba.fastjson.serializer.ObjectSerializer;
import com.alibaba.fastjson.serializer.SerializeConfig;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.lwd.utils.DateUtil;

import java.io.IOException;
import java.lang.reflect.Type;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by hugui on 4/18/14.
 */
public class JsonUtil {

    // 定制化fastjon mapping
    public static SerializeConfig defaultSerializeConfig = new SerializeConfig();
    private static DecimalFormat numberFormat = new DecimalFormat("0.00");

    static {
        Map<String, String> fieldPatternMap = new HashMap<String, String>(1);
        fieldPatternMap.put("gmtPerformance", DateUtil.YMD);
        defaultSerializeConfig.put(Date.class, new DateFormatSerializer(DateUtil.YMD_HMS, fieldPatternMap));
        defaultSerializeConfig.put(Double.class, new ObjectSerializer() {
            @Override
            public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) throws IOException {
                if (object == null) {
                    serializer.getWriter().writeNull();
                    return;
                }
                Double data = (Double) object;
                String text = numberFormat.format(data);
                serializer.write(text);
            }
        });
    }

    public static <T> T jsonToObject(String json, Type type) {
        if (json == null || "".equals(json.trim())) {
            return null;
        }
        return JSONObject.parseObject(json, type);
    }

    public static <T> T jsonToObject(String json, TypeReference<T> type) {
        if (json == null || "".equals(json.trim())) {
            return null;
        }
        return JSONObject.parseObject(json, type);
    }

    public static String objectToJsonString(Object obj) {
        if (obj == null) {
            return null;
        }
        return JSONObject.toJSONString(obj, defaultSerializeConfig, SerializerFeature.DisableCircularReferenceDetect);
    }

    public static String objectToJsonString(Object obj, SerializerFeature features) {
        if (obj == null) {
            return null;
        }
        return JSONObject.toJSONString(obj, features);
    }

    public static JSONObject objectToJson(Object obj) {
        if (obj == null) {
            return null;
        }
        return (JSONObject) JSON.toJSON(obj);
    }

    public static JSONArray strToJsonArray(String obj) {
        if (obj == null || "".equals(obj.trim())) {
            return null;
        }
        return JSON.parseArray(obj);
    }

    public static JSONObject strToJson(String obj) {
        return JSON.parseObject(obj);
    }

    static class DateFormatSerializer implements ObjectSerializer {

        private final String defaultPattern;
        private Map<String, String> fieldPatternMap;

        public DateFormatSerializer(String pattern) {
            this.defaultPattern = pattern;
        }

        public DateFormatSerializer(String pattern, Map<String, String> fieldPatternMap) {
            this.defaultPattern = pattern;
            this.fieldPatternMap = fieldPatternMap;
            if (fieldPatternMap == null) {
                this.fieldPatternMap = new HashMap<String, String>(1);
            }
        }

        @Override
        public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) throws IOException {
            if (object == null) {
                serializer.getWriter().writeNull();
                return;
            }

            Date date = (Date) object;
            SimpleDateFormat format = null;
            if (fieldPatternMap.containsKey(fieldName)) {
                format = new SimpleDateFormat(fieldPatternMap.get(fieldName));
            } else {
                format = new SimpleDateFormat(defaultPattern);
            }

            String text = format.format(date);
            serializer.write(text);
        }
    }
}
